/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/**
 * @file 
 * Implementation file of LwpDrawObjcts and associated class like LwpDrawGroup, LwpDrawRectange
 *	and so on.
 */
#include "lwpglobalmgr.hxx"
#include "lwpdrawobj.hxx"
#include "lwptools.hxx"
#include <tools/stream.hxx>

#include "xfilter/xfframe.hxx"

#include "xfilter/xfstylemanager.hxx"
#include "xfilter/xfdrawstyle.hxx"
#include "xfilter/xftextstyle.hxx"
#include "xfilter/xfparastyle.hxx"
#include "xfilter/xfimagestyle.hxx"
#include "xfilter/xftextboxstyle.hxx"
#include "xfilter/xfparagraph.hxx"
#include "xfilter/xftextspan.hxx"
#include "xfilter/xffont.hxx"

#include "xfilter/xfdrawrect.hxx"
#include "xfilter/xfdrawpath.hxx"
#include "xfilter/xfdrawline.hxx"
#include "xfilter/xfdrawpolygon.hxx"
#include "xfilter/xfdrawellipse.hxx"
#include "xfilter/xfdrawcircle.hxx"
#include "xfilter/xfimage.hxx"

#include "lwpcharsetmgr.hxx"
#include "lwpsdwrect.hxx"

/**
 * @descr   Constructor of class LwpDrawObj
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawObj::LwpDrawObj(SvStream * pStream, DrawingOffsetAndScale* pTransData) :
m_pStream(pStream), m_pTransData(pTransData), m_eType(OT_UNDEFINED)
{
	this->ReadObjHeaderRecord();
}

/**
 * @descr   read the header record data of lwp-sdw-object
 */
void LwpDrawObj::ReadObjHeaderRecord()
{
	//flags
	m_pStream->SeekRel(1);

	//record Length
	m_pStream->Read(&m_aObjHeader.nRecLen, sizeof(m_aObjHeader.nRecLen));

	//boundrect
	m_pStream->Read(&m_aObjHeader.nLeft, sizeof(m_aObjHeader.nLeft)); 
	m_pStream->Read(&m_aObjHeader.nTop, sizeof(m_aObjHeader.nTop)); 
	m_pStream->Read(&m_aObjHeader.nRight, sizeof(m_aObjHeader.nRight)); 
	m_pStream->Read(&m_aObjHeader.nBottom, sizeof(m_aObjHeader.nBottom)); 
	
	//nextObj, prevObj
	m_pStream->SeekRel(4);
}

/**
 * @descr   read the style of closed lwp-sdw-object like: rectangle, ellipse and so on.
 */
void LwpDrawObj::ReadClosedObjStyle()
{
	if ((m_eType != OT_POLYGON) && (m_eType != OT_TEXTART))
	{
		m_pStream->SeekRel(8);
	}

	m_pStream->Read(&m_aClosedObjStyleRec.nLineWidth, sizeof(m_aClosedObjStyleRec.nLineWidth));
	m_pStream->Read(&m_aClosedObjStyleRec.nLineStyle, sizeof(m_aClosedObjStyleRec.nLineStyle));

	// pen color
	m_pStream->Read(&m_aClosedObjStyleRec.aPenColor.nR, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aPenColor.nG, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aPenColor.nB, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aPenColor.unused, 1);

	// foreground color
	m_pStream->Read(&m_aClosedObjStyleRec.aForeColor.nR, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aForeColor.nG, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aForeColor.nB, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aForeColor.unused, 1);

	// background color
	m_pStream->Read(&m_aClosedObjStyleRec.aBackColor.nR, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aBackColor.nG, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aBackColor.nB, 1);
	m_pStream->Read(&m_aClosedObjStyleRec.aBackColor.unused, 1);

	// fill style
	m_pStream->Read(&m_aClosedObjStyleRec.nFillType, sizeof(m_aClosedObjStyleRec.nFillType));
	m_pStream->Read(m_aClosedObjStyleRec.pFillPattern, sizeof(m_aClosedObjStyleRec.pFillPattern));
}

/**
 * @descr   set fill style of drawing objects
 * @param   pStyle   pointer of the drawing xfstyle.
 */
void LwpDrawObj::SetFillStyle(XFDrawStyle* pStyle)
{
	if (!pStyle)
	{
		assert(false);
		return;
	}
	
	XFColor aForeColor(m_aClosedObjStyleRec.aForeColor.nR,
		m_aClosedObjStyleRec.aForeColor.nG, m_aClosedObjStyleRec.aForeColor.nB);
	XFColor aBackColor(m_aClosedObjStyleRec.aBackColor.nR,
		m_aClosedObjStyleRec.aBackColor.nG, m_aClosedObjStyleRec.aBackColor.nB);
	
	switch (m_aClosedObjStyleRec.nFillType)
	{
	default: //fall through!
	case FT_TRANSPARENT:
		{
			// set fill style : none
			break;
		}
	case FT_SOLID:
		{
			pStyle->SetAreaColor(aForeColor);
			break;
		}
	case FT_HORZHATCH:
		{
			pStyle->SetAreaColor(aBackColor);
			pStyle->SetAreaLineStyle(enumXFAreaLineSingle, 0, 0.12, aForeColor);
			break;
		}
	case FT_VERTHATCH:
		{
			pStyle->SetAreaColor(aBackColor);
			pStyle->SetAreaLineStyle(enumXFAreaLineSingle, 90, 0.12, aForeColor);
			break;
		}
	case FT_FDIAGHATCH:
		{
			pStyle->SetAreaColor(aBackColor);
			pStyle->SetAreaLineStyle(enumXFAreaLineSingle, 135, 0.09, aForeColor);
			break;
		}
	case FT_BDIAGHATCH:
		{
			pStyle->SetAreaColor(aBackColor);
			pStyle->SetAreaLineStyle(enumXFAreaLineSingle, 45, 0.09, aForeColor);
			break;
		}
	case FT_CROSSHATCH:
		{
			pStyle->SetAreaColor(aBackColor);
			pStyle->SetAreaLineStyle(enumXFAreaLineCrossed, 0, 0.12, aForeColor);
			break;
		}
	case FT_DIAGCROSSHATCH:
		{
			pStyle->SetAreaColor(aBackColor);
			pStyle->SetAreaLineStyle(enumXFAreaLineCrossed, 45, 0.095, aForeColor);			
			break;
		}
	}
}

/**
 * @descr   set line/border style of drawing objects.
 * @param   pStyle   pointer of the drawing xfstyle.
 * @param   nWidth   width of line/border.
 * @param   nLineStyle   flag of line/border style: none, dot or solid.
 * @param   rColor   color of line/border.
 */
void LwpDrawObj::SetLineStyle(XFDrawStyle* pStyle, sal_uInt8 nWidth, sal_uInt8 nLineStyle,
	const SdwColor& rColor)
{
	if (!pStyle)
	{
		assert(false);
		return;
	}
	if (nWidth == 0)
	{
		nLineStyle = LS_NULL;
	}
	
	if (nLineStyle == LS_NULL)
	{
		// set stroke:none
		return;
	}

	if (nLineStyle == LS_DOT)
	{
		pStyle->SetLineDashStyle(enumXFLineDash, 1, 1, 0.05, 0.05, 0.05);
	}

	// line width
	double fWidth = (double)nWidth/TWIPS_PER_CM;

	// line color
	XFColor aXFColor(rColor.nR, rColor.nG, rColor.nB);
	
	pStyle->SetLineStyle(fWidth, aXFColor);
}

/**
 * @descr   set position of a drawing object in the frame.
 * @param   pObj   pointer of the xf-drawing object
 */
void LwpDrawObj::SetPosition(XFFrame* pObj)
{
	double fOffsetX = 0.00, fOffsetY = 0.00;
	double fScaleX = 1.00, fScaleY = 1.00;
	if (m_pTransData)
	{
		fOffsetX = m_pTransData->fOffsetX;
		fOffsetY = m_pTransData->fOffsetY;
		fScaleX = m_pTransData->fScaleX;
		fScaleY = m_pTransData->fScaleY;
	}
	
	pObj->SetPosition((double)m_aObjHeader.nLeft/TWIPS_PER_CM * fScaleX+ fOffsetX,
		(double)m_aObjHeader.nTop/TWIPS_PER_CM * fScaleY + fOffsetY,
		(double)(m_aObjHeader.nRight-m_aObjHeader.nLeft)/TWIPS_PER_CM * fScaleX,
		(double)(m_aObjHeader.nBottom-m_aObjHeader.nTop)/TWIPS_PER_CM * fScaleY);
}

/**
 * @descr   set arrowhead of a xf-drawing object. only opened drawing objects can be assigned arrowheads
 * @param   pOpenedObjStyle   the xf-drawing object which will be set arrowhead.
 * @param   nArrowFlag   arrowhead flags of the object.
 */
void LwpDrawObj::SetArrowHead(XFDrawStyle* pOpenedObjStyle, sal_uInt8 nArrowFlag, sal_uInt8 nLineWidth)
{
	// no arrowhead
	if (!nArrowFlag)
	{
		return;
	}

	if (!pOpenedObjStyle)
	{
		assert(false);
		return;
	}

	// arrowhead flag of an object's start side
	sal_uInt8 nLeftArrow = nArrowFlag & 0x0F;

	// arrowhead flag of an object's end side
	sal_uInt8 nRightArrow = (nArrowFlag & 0xF0) >> 4;

	double fWidth_inch = (double)nLineWidth/TWIPS_PER_CM;
	double fArrowSize_inch = fWidth_inch + 0.08;
	double fArrowSize = fArrowSize_inch * CM_PER_INCH;

	if (nLeftArrow)
	{
		pOpenedObjStyle->SetArrowStart( this->GetArrowName(nLeftArrow), fArrowSize, sal_True);
	}
	if (nRightArrow)
	{
		pOpenedObjStyle->SetArrowEnd( this->GetArrowName(nRightArrow), fArrowSize, sal_True);
	}
	
}

/**
 * @descr   get arrow style name according to the flag.
 * @param   nArrowStyle   style of the arrowhead.
 * @return   nWhichSide   style name of the arrowhead.
 */
rtl::OUString LwpDrawObj::GetArrowName(sal_uInt8 nArrowStyle)
{
	// style name of arrowhead
	rtl::OUString aArrowName;
	
	switch(nArrowStyle)
	{
	default:
	case AH_ARROW_FULLARROW:
		aArrowName = rtl::OUString::createFromAscii("Symmetric arrow");
		break;
	case AH_ARROW_HALFARROW:
		aArrowName = rtl::OUString::createFromAscii("Arrow concave");
		break;
	case AH_ARROW_LINEARROW:
		aArrowName = rtl::OUString::createFromAscii("arrow100");
		break;
	case AH_ARROW_INVFULLARROW:
		aArrowName = rtl::OUString::createFromAscii("reverse arrow");
		break;
	case AH_ARROW_INVHALFARROW:
		aArrowName = rtl::OUString::createFromAscii("reverse concave arrow");
		break;
	case AH_ARROW_INVLINEARROW:
		aArrowName = rtl::OUString::createFromAscii("reverse line arrow");
		break;
	case AH_ARROW_TEE:
		aArrowName = rtl::OUString::createFromAscii("Dimension lines");
		break;
	case AH_ARROW_SQUARE:
		aArrowName = rtl::OUString::createFromAscii("Square");
		break;
	case AH_ARROW_CIRCLE:
		aArrowName = rtl::OUString::createFromAscii("Circle");
		break;
	}

	return aArrowName;
}

/**
 * @descr   template method of creating drawing object from Lwp-Model to XF-Model
 * @return   pointer of the drawing object of XF-Model.
 */
XFFrame* LwpDrawObj::CreateXFDrawObject()
{
	// read records
	this->Read();

	// register style
	rtl::OUString aStyleName = this->RegisterStyle();

	// create XF-Objects
	XFFrame* pXFObj = NULL;
	if (m_pTransData
		&& FABS(m_pTransData->fOffsetX - m_pTransData->fLeftMargin) < THRESHOLD
		&& FABS(m_pTransData->fOffsetY - m_pTransData->fTopMargin) < THRESHOLD
		&& FABS(m_pTransData->fScaleX - 1.0) < THRESHOLD
		&& FABS(m_pTransData->fScaleY - 1.0) < THRESHOLD)
	{
		pXFObj = this->CreateStandardDrawObj(aStyleName);
	}
	else
	{
		pXFObj = this->CreateDrawObj(aStyleName);
	}

	// set anchor type
	if (pXFObj)
	{
		pXFObj->SetAnchorType(enumXFAnchorFrame);
	}
	
	return pXFObj;
}

/**
 * @descr   Constructor of class LwpDrawLine
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawLine::LwpDrawLine(SvStream * pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData)
{
}

/**
 * @descr   reading function of class LwpDrawLine
 */
void LwpDrawLine::Read()
{
	m_pStream->Read(&m_aLineRec.nStartX, sizeof(m_aLineRec.nStartX)); 
	m_pStream->Read(&m_aLineRec.nStartY, sizeof(m_aLineRec.nStartY)); 
	m_pStream->Read(&m_aLineRec.nEndX, sizeof(m_aLineRec.nEndX)); 
	m_pStream->Read(&m_aLineRec.nEndY, sizeof(m_aLineRec.nEndY)); 
	m_pStream->Read(&m_aLineRec.nLineWidth, sizeof(m_aLineRec.nLineWidth)); 
	m_pStream->Read(&m_aLineRec.nLineEnd,sizeof(m_aLineRec.nLineEnd)); 
	m_pStream->Read(&m_aLineRec.nLineStyle, sizeof(m_aLineRec.nLineStyle));

	m_pStream->Read(&m_aLineRec.aPenColor.nR, 1);
	m_pStream->Read(&m_aLineRec.aPenColor.nG, 1);
	m_pStream->Read(&m_aLineRec.aPenColor.nB, 1);
	m_pStream->Read(&m_aLineRec.aPenColor.unused, 1);
}

rtl::OUString LwpDrawLine::RegisterStyle()
{
	XFDrawStyle* pStyle = new XFDrawStyle();

	// set line style
	this->SetLineStyle(pStyle, m_aLineRec.nLineWidth, m_aLineRec.nLineStyle, m_aLineRec.aPenColor);

	// set arrow head
	this->SetArrowHead(pStyle, m_aLineRec.nLineEnd, m_aLineRec.nLineWidth);
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();

}

XFFrame* LwpDrawLine::CreateDrawObj(const rtl::OUString& rStyleName )
{
	XFDrawPath* pLine = new XFDrawPath();
	pLine->MoveTo(XFPoint((double)(m_aLineRec.nStartX)/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)(m_aLineRec.nStartY)/TWIPS_PER_CM * m_pTransData->fScaleY));
	pLine->LineTo(XFPoint((double)(m_aLineRec.nEndX)/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)(m_aLineRec.nEndY)/TWIPS_PER_CM * m_pTransData->fScaleY));
	this->SetPosition(pLine);
	
	pLine->SetStyleName(rStyleName);

	return pLine;
}

XFFrame* LwpDrawLine::CreateStandardDrawObj(const  OUString& rStyleName)
{
	XFDrawLine* pLine = new XFDrawLine();
	pLine->SetStartPoint((double)(m_aLineRec.nStartX)/TWIPS_PER_CM,(double)(m_aLineRec.nStartY)/TWIPS_PER_CM);
	pLine->SetEndPoint((double)(m_aLineRec.nEndX)/TWIPS_PER_CM,(double)(m_aLineRec.nEndY)/TWIPS_PER_CM);

	pLine->SetStyleName(rStyleName);
	return pLine;
}

/**
 * @descr   Constructor of class LwpDrawPolyLine
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawPolyLine::LwpDrawPolyLine(SvStream * pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData), m_pVector(NULL)
{
}
LwpDrawPolyLine::~LwpDrawPolyLine()
{
	if (m_pVector)
	{
		delete [] m_pVector;
		m_pVector = NULL;
	}
}

/**
 * @descr   reading function of class LwpDrawPolyLine
 */
void LwpDrawPolyLine::Read()
{
		m_pStream->Read(&m_aPolyLineRec.nLineWidth, 1); 
		m_pStream->Read(&m_aPolyLineRec.nLineEnd, 1); 
		m_pStream->Read(&m_aPolyLineRec.nLineStyle, 1); 
		m_pStream->Read(&m_aPolyLineRec.aPenColor.nR, 1);
		m_pStream->Read(&m_aPolyLineRec.aPenColor.nG, 1);
		m_pStream->Read(&m_aPolyLineRec.aPenColor.nB, 1);
		m_pStream->Read(&m_aPolyLineRec.aPenColor.unused, 1);
		m_pStream->Read(&m_aPolyLineRec.nNumPoints, 2); 

		m_pVector= new SdwPoint [m_aPolyLineRec.nNumPoints];

		for (sal_uInt16 nC = 0; nC < m_aPolyLineRec.nNumPoints; nC++)
		{
			m_pStream->Read(&m_pVector[nC].x,2); 
			m_pStream->Read(&m_pVector[nC].y,2); 
		}
}

rtl::OUString LwpDrawPolyLine::RegisterStyle()
{
	XFDrawStyle* pStyle = new XFDrawStyle();

	// set line style
	this->SetLineStyle(pStyle, m_aPolyLineRec.nLineWidth, m_aPolyLineRec.nLineStyle,
		m_aPolyLineRec.aPenColor);

	// set arrow head
	this->SetArrowHead(pStyle, m_aPolyLineRec.nLineEnd, m_aPolyLineRec.nLineWidth);
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawPolyLine::CreateDrawObj(const rtl::OUString& rStyleName )
{
	XFDrawPath* pPolyline = new XFDrawPath();
	pPolyline->MoveTo(XFPoint((double)m_pVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)m_pVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	for (sal_uInt8 nC = 1; nC < m_aPolyLineRec.nNumPoints; nC++)
	{
		pPolyline->LineTo(XFPoint((double)m_pVector[nC].x/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)m_pVector[nC].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	}
	this->SetPosition(pPolyline);
	
	pPolyline->SetStyleName(rStyleName);
	
	return pPolyline;
}

XFFrame* LwpDrawPolyLine::CreateStandardDrawObj(const  OUString& rStyleName)
{
	XFDrawPolyline* pPolyline = new XFDrawPolyline();
	for (sal_uInt8 nC = 0; nC < m_aPolyLineRec.nNumPoints; nC++)
	{
		pPolyline->AddPoint((double)m_pVector[nC].x/TWIPS_PER_CM,
			(double)m_pVector[nC].y/TWIPS_PER_CM);
	}

	pPolyline->SetStyleName(rStyleName);

	return pPolyline;
}

/**
 * @descr   Constructor of class LwpDrawPolygon
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawPolygon::LwpDrawPolygon(SvStream * pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData)
{
}
LwpDrawPolygon::~LwpDrawPolygon()
{
	if (m_pVector)
	{
		delete m_pVector;
		m_pVector = NULL;
	}
}

/**
 * @descr   reading function of class LwpDrawPolygon
 */
void LwpDrawPolygon::Read()
{
	this->ReadClosedObjStyle();
	m_pStream->Read(&m_nNumPoints, sizeof(m_nNumPoints));

	m_pVector = new SdwPoint [m_nNumPoints];

	for (sal_uInt16 nC = 0; nC < m_nNumPoints; nC++)
	{
		m_pStream->Read(&m_pVector[nC].x, 2); 
		m_pStream->Read(&m_pVector[nC].y, 2); 
	}
}

rtl::OUString LwpDrawPolygon::RegisterStyle()
{
	XFDrawStyle* pStyle = new XFDrawStyle();

	// set line style
	this->SetLineStyle(pStyle, m_aClosedObjStyleRec.nLineWidth, m_aClosedObjStyleRec.nLineStyle,
		m_aClosedObjStyleRec.aPenColor);

	// set fill style
	this->SetFillStyle(pStyle);

	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawPolygon::CreateDrawObj(const rtl::OUString& rStyleName)
{
	XFDrawPath* pPolygon = new XFDrawPath();
	pPolygon->MoveTo(XFPoint((double)m_pVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)m_pVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	for (sal_uInt16 nC = 1; nC < m_nNumPoints; nC++)
	{
		pPolygon->LineTo(XFPoint((double)m_pVector[nC].x/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)m_pVector[nC].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	}
	pPolygon->ClosePath();
	this->SetPosition(pPolygon);
	pPolygon->SetStyleName(rStyleName);

	return pPolygon;
}

XFFrame* LwpDrawPolygon::CreateStandardDrawObj(const  OUString& rStyleName)
{
	XFDrawPolygon* pPolygon = new XFDrawPolygon();
	for (sal_uInt16 nC = 0; nC < m_nNumPoints; nC++)
	{
		pPolygon->AddPoint((double)m_pVector[nC].x/TWIPS_PER_CM,
			(double)m_pVector[nC].y/TWIPS_PER_CM);
	}

	pPolygon->SetStyleName(rStyleName);

	return pPolygon;
}

/**
 * @descr   Constructor of class LwpDrawRectangle
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawRectangle::LwpDrawRectangle(SvStream * pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData)
{
}

/**
 * @descr   reading function of class LwpDrawRectangle
 */
void LwpDrawRectangle::Read()
{
	this->ReadClosedObjStyle();
	

	sal_uInt8 nPointsCount;
	if (m_eType == OT_RNDRECT)
	{
		nPointsCount = 16;
		m_pStream->SeekRel(4); // corner points
	}
	else
	{
		nPointsCount = 4;
	}
	
	for (sal_uInt8 nC = 0; nC < nPointsCount; nC++)
	{
		m_pStream->Read(&m_aVector[nC].x,2); 
		m_pStream->Read(&m_aVector[nC].y,2); 
	}
}

rtl::OUString LwpDrawRectangle::RegisterStyle()
{
	XFDrawStyle* pStyle = new XFDrawStyle();

	// set line style
	this->SetLineStyle(pStyle, m_aClosedObjStyleRec.nLineWidth, m_aClosedObjStyleRec.nLineStyle,
		m_aClosedObjStyleRec.aPenColor);

	// set fill style
	this->SetFillStyle(pStyle);
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawRectangle::CreateDrawObj(const rtl::OUString& rStyleName)
{
	if (m_eType == OT_RNDRECT)
	{
		return this->CreateRoundedRect(rStyleName);
	}
	else
	{
		XFDrawPath* pRect = new XFDrawPath();
		pRect->MoveTo(XFPoint((double)m_aVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)m_aVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));
		for (sal_uInt8 nC = 1; nC < 4; nC++)
		{
			pRect->LineTo(XFPoint((double)m_aVector[nC].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[nC].y/TWIPS_PER_CM * m_pTransData->fScaleY));
		}
		pRect->LineTo(XFPoint((double)m_aVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));		
		pRect->ClosePath(sal_True);
		this->SetPosition(pRect);

		pRect->SetStyleName(rStyleName);

		return pRect;
	}
}

XFFrame* LwpDrawRectangle::CreateRoundedRect(const rtl::OUString& rStyleName)
{
	XFDrawPath* pRoundedRect = new XFDrawPath();
	pRoundedRect->MoveTo(XFPoint((double)m_aVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
	(double)m_aVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));

	sal_uInt8 nPtIndex = 1;
	for (sal_uInt8 nC = 0; nC < 7; nC++)
	{
		if (nC%2 == 0)
		{
			XFPoint aCtrl1((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
			nPtIndex++;
			XFPoint aCtrl2((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
			nPtIndex++;
			XFPoint aDest((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
			nPtIndex++;
			
			pRoundedRect->CurveTo(aDest, aCtrl1, aCtrl2);
		}
		else
		{
			XFPoint aDest((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
			nPtIndex++;
			
			pRoundedRect->LineTo(aDest);
		}
	}

	pRoundedRect->LineTo(XFPoint((double)m_aVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
				(double)m_aVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	pRoundedRect->ClosePath(sal_True);
	this->SetPosition(pRoundedRect);

	pRoundedRect->SetStyleName(rStyleName);

	return pRoundedRect;
}

XFFrame* LwpDrawRectangle::CreateStandardDrawObj(const  OUString& rStyleName)
{
	if (m_eType == OT_RNDRECT)
	{
		return this->CreateRoundedRect(rStyleName);
	}
	else
	{
		XFDrawRect* pRect = new XFDrawRect();
		double fStartX, fStartY, fWidth, fHeight;
		double fRotAngle = 0.0;
		SdwRectangle aSdwRect;
		Rectangle aOriginalRect;
		Point aPt0, aPt1, aPt2, aPt3;

		aPt0.setX(m_aVector[0].x); aPt0.setY(m_aVector[0].y);
		aPt1.setX(m_aVector[1].x); aPt1.setY(m_aVector[1].y);
		aPt2.setX(m_aVector[2].x); aPt2.setY(m_aVector[2].y);
		aPt3.setX(m_aVector[3].x); aPt3.setY(m_aVector[3].y);

		aSdwRect = SdwRectangle(aPt0, aPt1, aPt2, aPt3);
		if (aSdwRect.IsRectRotated())
		{
			aOriginalRect = aSdwRect.GetOriginalRect();
			fRotAngle = aSdwRect.GetRotationAngle();
		}
		else
		{
			aOriginalRect = Rectangle(aPt0, aPt2);
		}

		fStartX = aOriginalRect.TopLeft().X();
		fStartY = aOriginalRect.TopLeft().Y();
		fWidth = aOriginalRect.GetWidth();
		fHeight = aOriginalRect.GetHeight();

		pRect->SetStartPoint(XFPoint(fStartX/TWIPS_PER_CM + m_pTransData->fOffsetX,
			fStartY/TWIPS_PER_CM + m_pTransData->fOffsetY));
		pRect->SetSize(fWidth/TWIPS_PER_CM, fHeight/TWIPS_PER_CM);

		if (aSdwRect.IsRectRotated())
		{
			pRect->SetRotate( fRotAngle / PI * 180);// aXFCenter);
		}

		pRect->SetStyleName(rStyleName);

		return pRect;
	}
}

/**
 * @descr   Constructor of class LwpDrawEllipse
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawEllipse::LwpDrawEllipse(SvStream * pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData)
{
}

/**
 * @descr   reading function of class LwpDrawEllipse
 */
void LwpDrawEllipse::Read()
{
	this->ReadClosedObjStyle();
	
	for (sal_uInt8 nC = 0; nC < 13; nC++)
	{
		m_pStream->Read(&m_aVector[nC].x,2); 
		m_pStream->Read(&m_aVector[nC].y,2); 
	}
}

rtl::OUString LwpDrawEllipse::RegisterStyle()
{
	XFDrawStyle* pStyle = new XFDrawStyle();

	// set line style
	this->SetLineStyle(pStyle, m_aClosedObjStyleRec.nLineWidth, m_aClosedObjStyleRec.nLineStyle,
		m_aClosedObjStyleRec.aPenColor);

	// set fill style
	this->SetFillStyle(pStyle);

	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawEllipse::CreateDrawObj(const rtl::OUString& rStyleName )
{
	XFDrawPath* pEllipse = new XFDrawPath();
	pEllipse->MoveTo(XFPoint((double)m_aVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	sal_uInt8 nPtIndex = 1;
	for (sal_uInt8 nC = 0; nC < 4; nC++)
	{
		XFPoint aCtrl1((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
		nPtIndex++;
		XFPoint aCtrl2((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
		nPtIndex++;
		XFPoint aDest((double)m_aVector[nPtIndex].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[nPtIndex].y/TWIPS_PER_CM * m_pTransData->fScaleY);
		nPtIndex++;

		pEllipse->CurveTo(aDest, aCtrl1, aCtrl2);
	}
	pEllipse->ClosePath(sal_True);
	this->SetPosition(pEllipse);

	pEllipse->SetStyleName(rStyleName);

	return pEllipse;
}

XFFrame* LwpDrawEllipse::CreateStandardDrawObj(const  OUString& rStyleName)
{
	return this->CreateDrawObj(rStyleName);
}

/**
 * @descr   Constructor of class LwpDrawArc
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawArc::LwpDrawArc(SvStream * pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData)
{
}

/**
 * @descr   reading function of class LwpDrawArc
 */
void LwpDrawArc::Read()
{
	m_pStream->SeekRel(16);// arcRect, startPt, endPt

	m_pStream->Read(&m_aArcRec.nLineWidth, sizeof(m_aArcRec.nLineWidth));
	m_pStream->Read(&m_aArcRec.nLineStyle, sizeof(m_aArcRec.nLineStyle));
	m_pStream->Read(&m_aArcRec.aPenColor.nR, 1);
	m_pStream->Read(&m_aArcRec.aPenColor.nG, 1);
	m_pStream->Read(&m_aArcRec.aPenColor.nB, 1);
	m_pStream->Read(&m_aArcRec.aPenColor.unused, 1);
	m_pStream->Read(&m_aArcRec.nLineEnd, sizeof(m_aArcRec.nLineEnd));
	
	for (sal_uInt8 nC = 0; nC < 4; nC++)
	{
		m_pStream->Read(&m_aVector[nC].x,2); 
		m_pStream->Read(&m_aVector[nC].y,2); 
	}
}

rtl::OUString LwpDrawArc::RegisterStyle()
{
	XFDrawStyle* pStyle = new XFDrawStyle();

	// set line style
	this->SetLineStyle(pStyle, m_aArcRec.nLineWidth, m_aArcRec.nLineStyle,
		m_aArcRec.aPenColor);

	// set arrow head
	this->SetArrowHead(pStyle, m_aArcRec.nLineEnd, m_aArcRec.nLineWidth);

	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawArc::CreateDrawObj(const rtl::OUString& rStyleName )
{
	XFDrawPath* pArc = new XFDrawPath();
	pArc->MoveTo(XFPoint((double)m_aVector[0].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[0].y/TWIPS_PER_CM * m_pTransData->fScaleY));
	XFPoint aDest((double)m_aVector[3].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[3].y/TWIPS_PER_CM * m_pTransData->fScaleY);
	XFPoint aCtl1((double)m_aVector[1].x/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)m_aVector[1].y/TWIPS_PER_CM * m_pTransData->fScaleY);
	XFPoint aCtl2((double)m_aVector[2].x/TWIPS_PER_CM* m_pTransData->fScaleX,
		(double)m_aVector[2].y/TWIPS_PER_CM * m_pTransData->fScaleY);
	pArc->CurveTo(aDest, aCtl1, aCtl2);
//	pArc->CurveTo(XFPoint((double)m_aVector[3].x/TWIPS_PER_CM, (double)m_aVector[3].y/TWIPS_PER_CM),
//		XFPoint((double)m_aVector[1].x/TWIPS_PER_CM, (double)m_aVector[1].y/TWIPS_PER_CM),
//		XFPoint((double)m_aVector[2].x/TWIPS_PER_CM, (double)m_aVector[2].y/TWIPS_PER_CM));
	this->SetPosition(pArc);

	pArc->SetStyleName(rStyleName);
	
	return pArc;
}

XFFrame* LwpDrawArc::CreateStandardDrawObj(const  OUString& rStyleName)
{
	return this->CreateDrawObj(rStyleName);
}

/**
 * @descr   Constructor of class LwpDrawTextBox
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawTextBox::LwpDrawTextBox(SvStream* pStream) : LwpDrawObj(pStream)
{
}

LwpDrawTextBox::~LwpDrawTextBox()
{
	if (m_aTextRec.pTextString)
	{
		delete [] m_aTextRec.pTextString;
		m_aTextRec.pTextString = NULL;
	}
}

void LwpDrawTextBox::SetFontStyle(XFFont* pFont, SdwTextBoxRecord* pRec)
{
	// color
	XFColor aXFColor(pRec->aTextColor.nR, pRec->aTextColor.nG,
			pRec->aTextColor.nB);
	pFont->SetColor(aXFColor);
	//size
	pFont->SetFontSize(pRec->nTextSize/20);
	// bold
	pFont->SetBold((sal_Bool)((pRec->nTextAttrs & TA_BOLD) != 0));
	// italic
	pFont->SetItalic((sal_Bool)((pRec->nTextAttrs & TA_ITALIC) != 0));
	// strike-through
	if (pRec->nTextAttrs & TA_STRIKETHRU)
	{
		pFont->SetCrossout(enumXFCrossoutSignel);
	}
	else
	{
		pFont->SetCrossout(enumXFCrossoutNone);
	}
	// underline
	if (pRec->nTextAttrs & TA_UNDERLINE)
	{
		pFont->SetUnderline(enumXFUnderlineSingle);
	}
	else if (pRec->nTextAttrs & TA_WORDUNDERLINE)
	{
		pFont->SetUnderline(enumXFUnderlineSingle, sal_True);
	}
	else if (pRec->nTextAttrs & TA_DOUBLEUNDER)
	{
		pFont->SetUnderline(enumXFUnderlineDouble);
	}
	else
	{
		pFont->SetUnderline(enumXFUnderlineNone);
	}
	// small-caps
	if (pRec->nTextAttrs & TA_SMALLCAPS)
	{
		pFont->SetTransform(enumXFTransformSmallCaps);
	}
}

/**
 * @descr   reading function of class LwpDrawTextBox
 */
void LwpDrawTextBox::Read()
{
	m_pStream->Read(&m_aVector.x, 2);
	m_pStream->Read(&m_aVector.y, 2);
	m_pStream->Read(&m_aTextRec.nTextWidth, sizeof(m_aTextRec.nTextWidth));

	if (m_aTextRec.nTextWidth == 0)
	{
		m_aTextRec.nTextWidth = 1;
	}

	m_pStream->Read(&m_aTextRec.nTextHeight, sizeof(m_aTextRec.nTextHeight));
	m_pStream->Read(m_aTextRec.tmpTextFaceName, DRAW_FACESIZE);
	m_pStream->SeekRel(1);// PitchAndFamily

	m_pStream->Read(&m_aTextRec.nTextSize, sizeof(m_aTextRec.nTextSize));

	bool TextSizeIsCellHeight = true;
	if (m_aTextRec.nTextSize < 0)
	{
		TextSizeIsCellHeight = false;
		m_aTextRec.nTextSize = -m_aTextRec.nTextSize;
	}

	//color
	m_pStream->Read(&m_aTextRec.aTextColor.nR, 1); 
	m_pStream->Read(&m_aTextRec.aTextColor.nG, 1); 
	m_pStream->Read(&m_aTextRec.aTextColor.nB, 1);
	m_pStream->Read(&m_aTextRec.aTextColor.unused, 1); 

	m_pStream->Read(&m_aTextRec.nTextAttrs, sizeof(m_aTextRec.nTextAttrs));
	m_pStream->Read(&m_aTextRec.nTextCharacterSet, sizeof(m_aTextRec.nTextCharacterSet));
	m_pStream->Read(&m_aTextRec.nTextRotation, sizeof(m_aTextRec.nTextRotation));
	m_pStream->Read(&m_aTextRec.nTextExtraSpacing, sizeof(m_aTextRec.nTextExtraSpacing));

	/*#ifdef JAPANESE_ENABLED //For Amipro Support KOBA-WADA
		lubyte compText[3];
		lsshort TextLength;
		lubyte * pTextString;
		cBinaryData.GetUBytes(compText, 2);
		compText[2] = '\0';
		if (compText[0] == 0 && compText[1] == 0 && recLen > 105 )
		{
			// AmiPro R3.1J's extended text object format
			TextLength = recLen - 71 - 34;
			cBinaryData.SkipUBytes(32);

			pTextString = new lubyte[TextLength];

			LASSERT(pTextString != LNULL);

			cBinaryData.GetUBytes(pTextString, TextLength);
		}
		else
		{
			// AmiPro R3.X original text object format

			// some draw files in version 1.2 have an extra byte following '\0'.
			// can't rely on that, so read in the whole string into memory.
			TextLength = recLen - 71;
			pTextString = new lubyte[TextLength];

			LASSERT(pTextString != LNULL);

			strcpy((char *)pTextString, (const char *)compText);
			cBinaryData.GetUBytes(pTextString + 2, TextLength - 2);
		}
#else*/
		// some draw files in version 1.2 have an extra byte following '\0'.
		// can't rely on that, so read in the whole string into memory.

		// the 71 is the fixed length before text content in textbox record
		sal_Int16 TextLength = m_aObjHeader.nRecLen - 71;
		m_aTextRec.pTextString = new sal_uInt8 [TextLength];

		m_pStream->Read(m_aTextRec.pTextString, TextLength);

//#endif // AmiPro
	
}

rtl::OUString LwpDrawTextBox::RegisterStyle()
{
	XFParaStyle* pStyle = new XFParaStyle();

	// font style
	// the pFont need to be deleted myself?
	XFFont* pFont = new XFFont();

	rtl_TextEncoding aEncoding =  RTL_TEXTENCODING_MS_1252;
	rtl::OUString aFontName = rtl::OUString((sal_Char*)m_aTextRec.tmpTextFaceName,
		strlen((char*)m_aTextRec.tmpTextFaceName), aEncoding);
	pFont->SetFontName(aFontName);

	this->SetFontStyle(pFont, &m_aTextRec);

	pStyle->SetFont(pFont);
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawTextBox::CreateDrawObj(const rtl::OUString& rStyleName )
{
	XFFrame* pTextBox = new XFFrame(sal_True);
/*	this->SetPosition(pTextBox);
	XFRect aBoundRect((double)m_aObjHeader.nLeft/TWIPS_PER_CM, (double)m_aObjHeader.nTop/TWIPS_PER_CM,
		(double)(m_aObjHeader.nRight-m_aObjHeader.nLeft)/TWIPS_PER_CM, (double)(m_aObjHeader.nBottom-m_aObjHeader.nTop)/TWIPS_PER_CM);
	pTextBox->SetPosition(aBoundRect);*/

	sal_Int16 TextLength = m_aObjHeader.nRecLen - 71;
	rtl_TextEncoding aEncoding;
	if (!m_aTextRec.nTextCharacterSet)
	{
		aEncoding = gsl_getSystemTextEncoding();
	}
	else
	{
		// temporary code, need to create Encoding from the value of nTextCharacterSet
		aEncoding = LwpCharSetMgr::GetInstance()->GetTextCharEncoding();
	}

//	XFTextSpan* pTextSpan = new XFTextSpan();
//	pTextSpan->SetText(rtl::OUString((sal_Char*)m_aTextRec.pTextString, (TextLength-2), aEncoding));
//	pTextSpan->SetStyleName(rStyleName);

	XFParagraph* pXFPara = new XFParagraph();
	pXFPara->Add(rtl::OUString((sal_Char*)m_aTextRec.pTextString, (TextLength-2), aEncoding));
	pXFPara->SetStyleName(rStyleName);

	pTextBox->Add(pXFPara);
	this->SetPosition(pTextBox);

	/*
	XFFrameStyle* pBoxStyle = new XFFrameStyle();
	pBoxStyle->SetYPosType(enumXFFrameYPosFromTop, enumXFFrameYRelFrame);
	pBoxStyle->SetXPosType(enumXFFrameXPosFromLeft, enumXFFrameXRelFrame);
	pBoxStyle->SetPadding(0.0, 0.0, 0.0, 0.0);
	*/
	XFTextBoxStyle* pBoxStyle = new XFTextBoxStyle();
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	OUString sName = pXFStyleManager->AddStyle(pBoxStyle)->GetStyleName();
	pTextBox->SetStyleName(sName);
	
	//todo: add the interface for rotating textbox
//	if (m_aTextRec.nTextRotation)
//	{
//		double fAngle = double(3600-m_aTextRec.nTextRotation)/10;
//		pTextBox->SetRotate(fAngle);
//	}
	
	return pTextBox;
}

XFFrame* LwpDrawTextBox::CreateStandardDrawObj(const  OUString& rStyleName)
{
	return this->CreateDrawObj(rStyleName);
}

/**
 * @descr   Constructor of class LwpDrawTextBox
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawTextArt::LwpDrawTextArt(SvStream* pStream, DrawingOffsetAndScale* pTransData)
: LwpDrawObj(pStream, pTransData)
{
}

LwpDrawTextArt::~LwpDrawTextArt()
{
	if (m_aTextArtRec.aPath[0].pPts)
	{
		delete [] m_aTextArtRec.aPath[0].pPts;
		m_aTextArtRec.aPath[0].pPts = NULL;
	}
	if (m_aTextArtRec.aPath[1].pPts)
	{
		delete [] m_aTextArtRec.aPath[1].pPts;
		m_aTextArtRec.aPath[1].pPts = NULL;
	}
	if (m_aTextArtRec.pTextString)
	{
		delete [] m_aTextArtRec.pTextString;
		m_aTextArtRec.pTextString = NULL;
	}

}

void LwpDrawTextArt::CreateFWPath(XFDrawPath* pPath)
{
	sal_Int16 nX, nY;
	nX = (m_aTextArtRec.aPath[0].pPts[0].x + m_aTextArtRec.aPath[1].pPts[0].x) / 2;
	nY = (m_aTextArtRec.aPath[0].pPts[0].y + m_aTextArtRec.aPath[1].pPts[0].y) / 2;
	XFPoint aStart((double)nX/TWIPS_PER_CM * m_pTransData->fScaleX,
		(double)nY/TWIPS_PER_CM * m_pTransData->fScaleY);
	pPath->MoveTo(aStart);

	sal_uInt8 nPtIndex = 1;
	for (sal_uInt8 nC = 1; nC <= m_aTextArtRec.aPath[0].n; nC++)
	{
		nX = (m_aTextArtRec.aPath[0].pPts[nPtIndex].x + m_aTextArtRec.aPath[1].pPts[nPtIndex].x) / 2;
		nY = (m_aTextArtRec.aPath[0].pPts[nPtIndex].y + m_aTextArtRec.aPath[1].pPts[nPtIndex].y) / 2;
		XFPoint aCtrl1((double)nX/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)nY/TWIPS_PER_CM * m_pTransData->fScaleY);

		nPtIndex++;
		nX = (m_aTextArtRec.aPath[0].pPts[nPtIndex].x + m_aTextArtRec.aPath[1].pPts[nPtIndex].x) / 2;
		nY = (m_aTextArtRec.aPath[0].pPts[nPtIndex].y + m_aTextArtRec.aPath[1].pPts[nPtIndex].y) / 2;
		XFPoint aCtrl2((double)nX/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)nY/TWIPS_PER_CM * m_pTransData->fScaleY);

		nPtIndex++;
		nX = (m_aTextArtRec.aPath[0].pPts[nPtIndex].x + m_aTextArtRec.aPath[1].pPts[nPtIndex].x) / 2;
		nY = (m_aTextArtRec.aPath[0].pPts[nPtIndex].y + m_aTextArtRec.aPath[1].pPts[nPtIndex].y) / 2;
		XFPoint aDest((double)nX/TWIPS_PER_CM * m_pTransData->fScaleX,
			(double)nY/TWIPS_PER_CM * m_pTransData->fScaleY);

		pPath->CurveTo(aDest, aCtrl1, aCtrl2);
	}
}

void LwpDrawTextArt::Read()
{
	for (sal_uInt8 nC = 0; nC < 4; nC++)
	{
		m_pStream->Read(&m_aVector[nC].x, 2);
		m_pStream->Read(&m_aVector[nC].y, 2);		
	}

	this->ReadClosedObjStyle();
	m_aTextArtRec.aTextColor = m_aClosedObjStyleRec.aForeColor;
	
	m_pStream->Read(&m_aTextArtRec.nIndex, 1);
	m_pStream->Read(&m_aTextArtRec.nRotation, 2);

	sal_uInt16 nPointNumber;
	sal_Int16 nX, nY;
	m_pStream->Read(&nPointNumber, 2);
	m_aTextArtRec.aPath[0].n = nPointNumber;
	m_aTextArtRec.aPath[0].pPts = new SdwPoint [nPointNumber*3+1];
    sal_uInt16 nPt = 0;
	for ( nPt = 0; nPt <= nPointNumber*3; nPt++)
	{
		m_pStream->Read(&nX, 2);
		m_pStream->Read(&nY, 2);
		m_aTextArtRec.aPath[0].pPts[nPt].x = nX;
		m_aTextArtRec.aPath[0].pPts[nPt].y = nY;
	}

	m_pStream->Read(&nPointNumber, 2);
	m_aTextArtRec.aPath[1].n = nPointNumber;
	m_aTextArtRec.aPath[1].pPts = new SdwPoint [nPointNumber*3+1];
	for (nPt = 0; nPt <= nPointNumber*3; nPt++)
	{
		m_pStream->Read(&nX, 2);
		m_pStream->Read(&nY, 2);
		m_aTextArtRec.aPath[1].pPts[nPt].x = nX;
		m_aTextArtRec.aPath[1].pPts[nPt].y = nY;
	}

	m_pStream->SeekRel(1);

	m_pStream->Read(m_aTextArtRec.tmpTextFaceName, DRAW_FACESIZE);
	m_pStream->SeekRel(1);// PitchAndFamily

	m_pStream->Read(&m_aTextArtRec.nTextSize, sizeof(m_aTextArtRec.nTextSize));
	bool TextSizeIsCellHeight = true;
	if (m_aTextArtRec.nTextSize < 0)
	{
		TextSizeIsCellHeight = false;
		m_aTextArtRec.nTextSize = -m_aTextArtRec.nTextSize;
	}

	m_pStream->Read(&m_aTextArtRec.nTextAttrs, sizeof(m_aTextArtRec.nTextAttrs));
	m_pStream->Read(&m_aTextArtRec.nTextCharacterSet, sizeof(m_aTextArtRec.nTextCharacterSet));
//	m_pStream->Read(&m_aTextArtRec.nTextRotation, sizeof(m_aTextArtRec.nTextRotation));
	m_aTextArtRec.nTextRotation = 0;
	m_pStream->Read(&m_aTextArtRec.nTextExtraSpacing, sizeof(m_aTextArtRec.nTextExtraSpacing));

	const sal_uInt16 nTextArtFixedLength = 105;
	m_aTextArtRec.nTextLen = m_aObjHeader.nRecLen - nTextArtFixedLength
													- (m_aTextArtRec.aPath[0].n*3 + 1)*4
													- (m_aTextArtRec.aPath[1].n*3 + 1)*4;

	m_aTextArtRec.pTextString = new sal_uInt8 [m_aTextArtRec.nTextLen];
	m_pStream->Read(m_aTextArtRec.pTextString, m_aTextArtRec.nTextLen);
	m_aTextArtRec.pTextString[m_aTextArtRec.nTextLen-1] = 0;

}

rtl::OUString LwpDrawTextArt::RegisterStyle()
{
	XFParaStyle* pStyle = new XFParaStyle();

	// font style
	// the pFont need to be deleted myself?
	XFFont* pFont = new XFFont();

	rtl_TextEncoding aEncoding =  RTL_TEXTENCODING_MS_1252;
	rtl::OUString aFontName = rtl::OUString((sal_Char*)m_aTextArtRec.tmpTextFaceName,
		strlen((char*)m_aTextArtRec.tmpTextFaceName), aEncoding);
	pFont->SetFontName(aFontName);

	LwpDrawTextBox::SetFontStyle(pFont, &m_aTextArtRec);

	pStyle->SetFont(pFont);
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pStyle)->GetStyleName();
}

XFFrame* LwpDrawTextArt::CreateDrawObj(const rtl::OUString& rStyleName) 
{
	XFFrame* pRetObj = NULL;
	XFDrawStyle* pStyle = new XFDrawStyle();

	pRetObj = new XFDrawPath();
	XFDrawPath* pFWPath = static_cast<XFDrawPath*>(pRetObj);
	this->CreateFWPath(pFWPath);
	pStyle->SetFontWorkStyle(0, enumXFFWSlantY, enumXFFWAdjustAutosize);

	this->SetPosition(pRetObj);

	rtl_TextEncoding aEncoding;
	if (!m_aTextArtRec.nTextCharacterSet)
	{
		aEncoding = gsl_getSystemTextEncoding();
	}
	else
	{
		// temporary code, need to create Encoding from the value of nTextCharacterSet
		aEncoding = LwpCharSetMgr::GetInstance()->GetTextCharEncoding();
	}

	XFParagraph* pXFPara = new XFParagraph();
	pXFPara->Add(rtl::OUString((sal_Char*)m_aTextArtRec.pTextString, (m_aTextArtRec.nTextLen-1), aEncoding));
	pXFPara->SetStyleName(rStyleName);
	pRetObj->Add(pXFPara);

	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	pRetObj->SetStyleName(pXFStyleManager->AddStyle(pStyle)->GetStyleName());

	return pRetObj;
}

XFFrame* LwpDrawTextArt::CreateStandardDrawObj(const rtl::OUString& rStyleName )
{
	return this->CreateDrawObj(rStyleName);
}


/**
 * @descr   Constructor of class LwpDrawMetafile
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawMetafile::LwpDrawMetafile(SvStream* pStream) : LwpDrawObj(pStream)
{
}

/**
 * @descr   reading function of class LwpDrawMetafile
 */
void LwpDrawMetafile::Read()
{
	m_pStream->SeekRel(m_aObjHeader.nRecLen -16); 
}

/**
 * @descr   Constructor of class LwpDrawBitmap
 * @param   pStream   The memory stream which contains the lwp-sdw draw objects
 */
LwpDrawBitmap::LwpDrawBitmap(SvStream* pStream) : LwpDrawObj(pStream), m_pImageData(NULL)
{
}

LwpDrawBitmap::~LwpDrawBitmap()
{
	if (m_pImageData)
	{
		delete [] m_pImageData;
		m_pImageData = NULL;
	}
}

/**
 * @descr   reading function of class LwpDrawBitmap
 */
void LwpDrawBitmap::Read()
{
	m_pStream->Read(&m_aBmpRec.nTranslation, sizeof(m_aBmpRec.nTranslation));
	m_pStream->Read(&m_aBmpRec.nRotation, sizeof(m_aBmpRec.nRotation));

	// 20 == length of draw-specific fields.
	// 14 == length of bmp file header.
	m_aBmpRec.nFileSize = m_aObjHeader.nRecLen - 20 + 14;
	m_pImageData = new sal_uInt8 [m_aBmpRec.nFileSize];

	BmpInfoHeader2 aInfoHeader2;
	m_pStream->Read(&aInfoHeader2.nHeaderLen, 4);
	
	sal_uInt32 N;
	sal_uInt32 rgbTableSize;

	if (aInfoHeader2.nHeaderLen == sizeof(BmpInfoHeader))
	{
		m_pStream->Read(&aInfoHeader2.nWidth, 2);
		m_pStream->Read(&aInfoHeader2.nHeight, 2);
		m_pStream->Read(&aInfoHeader2.nPlanes, 2);
		m_pStream->Read(&aInfoHeader2.nBitCount, 2);

		N = aInfoHeader2.nPlanes * aInfoHeader2.nBitCount;
		if (N == 24)
		{
			rgbTableSize = 0;
		}
		else
		{
			rgbTableSize = 3 * (1 << N);
		}
	}
	else
	{
		m_pStream->Read(&aInfoHeader2.nWidth, 4);
		m_pStream->Read(&aInfoHeader2.nHeight, 4);
		m_pStream->Read(&aInfoHeader2.nPlanes, 2);
		m_pStream->Read(&aInfoHeader2.nBitCount, 2);
		N = aInfoHeader2.nPlanes * aInfoHeader2.nBitCount;
		if (N == 24)
		{
			rgbTableSize = 0;
		}
		else
		{
			rgbTableSize = 4 * (1 << N);
		}

	}

	sal_uInt32 nOffBits = 14 + aInfoHeader2.nHeaderLen + rgbTableSize;
	m_pImageData[0] = 'B';
	m_pImageData[1] = 'M';
	m_pImageData[2] = (sal_uInt8)m_aBmpRec.nFileSize;
	m_pImageData[3] = (sal_uInt8)(m_aBmpRec.nFileSize >> 8);
	m_pImageData[4] = (sal_uInt8)(m_aBmpRec.nFileSize >> 16);
	m_pImageData[5] = (sal_uInt8)(m_aBmpRec.nFileSize >> 24);
	m_pImageData[6] = 0;
	m_pImageData[7] = 0;
	m_pImageData[8] = 0;
	m_pImageData[9] = 0;
	m_pImageData[10] = (sal_uInt8)nOffBits;
	m_pImageData[11] = (sal_uInt8)(nOffBits >> 8);
	m_pImageData[12] = (sal_uInt8)(nOffBits >> 16);
	m_pImageData[13] = (sal_uInt8)(nOffBits >> 24);

	sal_uInt32 nDIBRemaining;
	sal_uInt8* pPicData = m_pImageData;
	if (aInfoHeader2.nHeaderLen== sizeof(BmpInfoHeader))
	{
		m_pImageData[14] = (sal_uInt8)aInfoHeader2.nHeaderLen;
		m_pImageData[15] = (sal_uInt8)(aInfoHeader2.nHeaderLen >> 8);
		m_pImageData[16] = (sal_uInt8)(aInfoHeader2.nHeaderLen >> 16);
		m_pImageData[17] = (sal_uInt8)(aInfoHeader2.nHeaderLen >> 24);
		m_pImageData[18] = (sal_uInt8)aInfoHeader2.nWidth;
		m_pImageData[19] = (sal_uInt8)(aInfoHeader2.nWidth >> 8);
		m_pImageData[20] = (sal_uInt8)aInfoHeader2.nHeight;
		m_pImageData[21] = (sal_uInt8)(aInfoHeader2.nHeight >> 8);
		m_pImageData[22] = (sal_uInt8)aInfoHeader2.nPlanes;
		m_pImageData[23] = (sal_uInt8)(aInfoHeader2.nPlanes >> 8);
		m_pImageData[24] = (sal_uInt8)aInfoHeader2.nBitCount;
		m_pImageData[25] = (sal_uInt8)(aInfoHeader2.nBitCount >> 8);

		nDIBRemaining = m_aBmpRec.nFileSize - 26;
		pPicData += 26*sizeof(sal_uInt8);
	}
	else
	{
		m_pImageData[14] = (sal_uInt8)aInfoHeader2.nHeaderLen;
		m_pImageData[15] = (sal_uInt8)(aInfoHeader2.nHeaderLen >> 8);
		m_pImageData[16] = (sal_uInt8)(aInfoHeader2.nHeaderLen >> 16);
		m_pImageData[17] = (sal_uInt8)(aInfoHeader2.nHeaderLen >> 24);
		m_pImageData[18] = (sal_uInt8)aInfoHeader2.nWidth;
		m_pImageData[19] = (sal_uInt8)(aInfoHeader2.nWidth >> 8);
		m_pImageData[20] = (sal_uInt8)(aInfoHeader2.nWidth >> 16);
		m_pImageData[21] = (sal_uInt8)(aInfoHeader2.nWidth >> 24);
		m_pImageData[22] = (sal_uInt8)aInfoHeader2.nHeight;
		m_pImageData[23] = (sal_uInt8)(aInfoHeader2.nHeight >> 8);
		m_pImageData[24] = (sal_uInt8)(aInfoHeader2.nHeight >> 16);
		m_pImageData[25] = (sal_uInt8)(aInfoHeader2.nHeight >> 24);
		m_pImageData[26] = (sal_uInt8)aInfoHeader2.nPlanes;
		m_pImageData[27] = (sal_uInt8)(aInfoHeader2.nPlanes >> 8);
		m_pImageData[28] = (sal_uInt8)aInfoHeader2.nBitCount;
		m_pImageData[29] = (sal_uInt8)(aInfoHeader2.nBitCount >> 8);

		nDIBRemaining = m_aBmpRec.nFileSize - 30;
		pPicData += 30*sizeof(sal_uInt8);
	}

	m_pStream->Read(pPicData, nDIBRemaining);

/*	FILE* pStream;
	pStream = fopen( "drawing_test.bmp", "w+" );
	fwrite(m_pImageData, sizeof(sal_uInt8), m_aBmpRec.nFileSize, pStream);
	fclose( pStream );
*/
}

rtl::OUString LwpDrawBitmap::RegisterStyle()
{
	XFImageStyle* pBmpStyle = new XFImageStyle();
	pBmpStyle->SetYPosType(enumXFFrameYPosFromTop, enumXFFrameYRelFrame);
	pBmpStyle->SetXPosType(enumXFFrameXPosFromLeft, enumXFFrameXRelFrame);
	
	XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
	return pXFStyleManager->AddStyle(pBmpStyle)->GetStyleName();
}

XFFrame* LwpDrawBitmap::CreateDrawObj(const rtl::OUString& rStyleName)
{
	XFImage* pImage = new XFImage();
	pImage->SetImageData(m_pImageData, m_aBmpRec.nFileSize);
	this->SetPosition(pImage);

	pImage->SetStyleName(rStyleName);
		
	return pImage;
}

XFFrame* LwpDrawBitmap::CreateStandardDrawObj(const  OUString& rStyleName)
{
	return this->CreateDrawObj(rStyleName);
}

